package handlers

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"ota-backend/config"
	"ota-backend/models"
	"ota-backend/storage"
	"path/filepath"
	"time"

	"ota-backend/utils"

	"github.com/gin-gonic/gin"
)

// FirmwareHandler 固件处理器
type FirmwareHandler struct {
	storage *storage.LocalStorage
}

// NewFirmwareHandler 创建固件处理器
func NewFirmwareHandler(storage *storage.LocalStorage) *FirmwareHandler {
	return &FirmwareHandler{
		storage: storage,
	}
}

// CreateFirmware 创建固件
func (h *FirmwareHandler) CreateFirmware(c *gin.Context) {
	// 解析表单数据
	version := c.PostForm("version")
	productID := c.PostForm("product_id")
	description := c.PostForm("description")

	// 验证必填字段
	if version == "" || productID == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "version, product_id 为必填字段"})
		return
	}

	// 检查产品是否存在
	var product models.Product
	if err := config.DB.First(&product, "id = ?", productID).Error; err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "产品不存在"})
		return
	}

	// 检查版本是否已存在
	/*var existingFirmware models.Firmware
	err := config.DB.Where("version = ? AND product_id = ?", version, productID).First(&existingFirmware).Error
	if err == nil {

	} else if err != gorm.ErrRecordNotFound {
		// 如果是其他错误（不是记录不存在），才返回错误
		c.JSON(http.StatusInternalServerError, gin.H{"error": "检查版本是否存在时发生错误"})
		return
	}
	// 如果是 ErrRecordNotFound，说明版本不存在，可以继续创建
	*/
	// 处理文件上传
	file, err := c.FormFile("file")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请上传固件文件"})
		return
	}
	log.Printf("===========file %s===========\n", file.Filename)

	// 验证文件类型
	allowedTypes := config.GetAllowedFileTypes()
	if !h.storage.ValidateFileType(file.Filename, allowedTypes) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "不支持的文件类型"})
		return
	}

	// 验证文件大小
	if file.Size > config.GetUploadMaxSize() {
		c.JSON(http.StatusBadRequest, gin.H{"error": "文件大小超过限制"})
		return
	}

	// 生成唯一文件名
	fileExt := filepath.Ext(file.Filename)
	if fileExt == "" {
		fileExt = ".bin"
	}
	newFilename := fmt.Sprintf("%s_%s%s", product.PublicID, version, fileExt)

	// 创建产品目录
	productDir := product.PublicID // 直接使用产品ID，不再添加files前缀
	if err := h.storage.CreateDir(productDir); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "创建产品目录失败"})
		return
	}

	// 保存文件
	src, err := file.Open()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "无法打开上传文件"})
		return
	}
	defer src.Close()

	filePath := filepath.Join(productDir, newFilename)
	log.Printf("保存文件: 路径=%s", filePath)
	_, err = h.storage.SaveFile(filePath, src)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "文件保存失败"})
		return
	}
	// 生成签名文件
	log.Printf("开始生成签名: 文件路径=%s, 签名类型=%s, 密钥长度=%d", filePath, product.SignType, len(product.SignKey))
	signature, err := utils.SignFile(filePath, utils.SignType(product.SignType), product.SignKey)
	if err != nil {
		// 删除已保存的文件
		log.Printf("===========签名失败详细信息===========")
		log.Printf("文件路径: %s", filePath)
		log.Printf("产品ID: %s", productID)
		log.Printf("签名类型: %s", product.SignType)
		log.Printf("签名类型(转换后): %s", utils.SignType(product.SignType))
		log.Printf("密钥长度: %d", len(product.SignKey))
		log.Printf("错误类型: %T", err)
		log.Printf("错误信息: %v", err)
		if err != nil {
			log.Printf("错误堆栈: %+v", err)
		}
		log.Printf("=====================================")
		h.storage.DeleteFile(filePath)
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("生成签名失败: %v", err)})
		return
	}
	log.Printf("签名生成成功: 签名长度=%d", len(signature))

	// 保存签名文件
	storagePath := config.GetStoragePath()
	fullSumFilePath := filepath.Join(storagePath, filePath+".sum")
	log.Printf("保存签名文件: 路径=%s", fullSumFilePath)

	err = os.WriteFile(fullSumFilePath, []byte(signature), 0644)
	if err != nil {
		// 删除已保存的文件
		log.Printf("===========保存签名失败详细信息===========")
		log.Printf("签名文件路径: %s", fullSumFilePath)
		log.Printf("错误信息: %v", err)
		log.Printf("=====================================")
		h.storage.DeleteFile(filePath)
		c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("保存签名文件失败: %v", err)})
		return
	}
	log.Printf("签名文件保存成功")

	// 创建固件记录ß
	firmware := models.Firmware{
		Version:     version,
		ProductID:   productID,
		Description: description,
		ReleaseTime: time.Now(),
		DownloadURL: fmt.Sprintf("%s/%s", product.PublicID, newFilename),
		FileSize:    file.Size,
		Signature:   signature,
	}

	if err := config.DB.Create(&firmware).Error; err != nil {
		// 删除已保存的文件
		h.storage.DeleteFile(filePath)
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	// 更新产品的最新版本
	if product.LatestVersion == "" || version > product.LatestVersion {
		config.DB.Model(&product).Update("latest_version", version)
	}

	c.JSON(http.StatusCreated, firmware)
}

// GetFirmwares 获取固件列表
func (h *FirmwareHandler) GetFirmwares(c *gin.Context) {
	productID := c.Query("product_id")

	var firmwares []models.Firmware
	query := config.DB.Preload("Product")

	if productID != "" {
		query = query.Where("product_id = ?", productID)
	}

	if err := query.Order("release_time DESC").Find(&firmwares).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, firmwares)
}

// GetFirmware 获取单个固件
func (h *FirmwareHandler) GetFirmware(c *gin.Context) {
	id := c.Param("id")

	var firmware models.Firmware
	if err := config.DB.Preload("Product").First(&firmware, "id = ?", id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "固件不存在"})
		return
	}

	c.JSON(http.StatusOK, firmware)
}

// DownloadFirmware 下载固件
func (h *FirmwareHandler) DownloadFirmware(c *gin.Context) {
	publicID := c.Param("product_id")
	filename := c.Param("filename")

	// 构建完整的文件路径 - 直接使用产品ID，不再添加files前缀
	filePath := filepath.Join(publicID, filename)

	// 检查文件是否存在
	if !h.storage.FileExists(filePath) {
		c.JSON(http.StatusNotFound, gin.H{"error": "固件文件不存在"})
		return
	}

	// 获取文件
	file, err := h.storage.GetFile(filePath)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "文件读取失败"})
		return
	}
	defer file.Close()

	// 设置响应头
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
	c.Header("Content-Type", "application/octet-stream")

	// 发送文件
	c.File(file.Name())
}

// DeleteFirmware 删除固件
func (h *FirmwareHandler) DeleteFirmware(c *gin.Context) {
	id := c.Param("id")

	var firmware models.Firmware
	if err := config.DB.Preload("Product").First(&firmware, "id = ?", id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "固件不存在"})
		return
	}

	// 构建固件文件路径 - 直接使用产品ID，不再添加files前缀
	productDir := firmware.Product.PublicID
	filename := filepath.Base(firmware.DownloadURL)
	firmwarePath := filepath.Join(productDir, filename)
	signaturePath := firmwarePath + ".sum"

	// 删除固件文件
	if h.storage.FileExists(firmwarePath) {
		if err := h.storage.DeleteFile(firmwarePath); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("固件文件删除失败: %v", err)})
			return
		}
	}

	// 删除签名文件
	if h.storage.FileExists(signaturePath) {
		if err := h.storage.DeleteFile(signaturePath); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("签名文件删除失败: %v", err)})
			return
		}
	}

	// 删除数据库记录
	if err := config.DB.Delete(&firmware).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "固件删除成功"})
}
